﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using System.Text;

namespace SmartProject.Data
{
    public enum DataType
    {
        DateTime,
        String,
        Integer,
        Boolean,
        Bytes
    }

    /// <summary>
    /// The DataParameter class is a generic placeholder for parameters for queries
    /// into the database.
    /// </summary>
    public class DataParameter
    {
        private byte[] _bytesValue;
        private DataType _dataType = DataType.String;
        private bool _isDirty = false;
        private string _name;
        private DateTime _dateTimeValue = DateTime.MinValue;
        private string _stringValue;
        private bool _booleanValue;
        private int _intValue = -1;
        private int _length;
        private object _lastValue;

        public DataParameter(string name, int length)
        {
            _name = name;
            _length = length;
            _dataType = DataType.String;
        }

        public DataParameter(string name, DataType dataType)
        {
            _name = name;
            _dataType = dataType;
        }

        public string GetName(bool isStoredProc)
        {
            if (isStoredProc)
            {
                StringBuilder text = new StringBuilder("@");
                text.Append(_name);
                return text.ToString();
            }
            else
            {
                return _name;
            }
        }

        public DataType Type
        {
            get { return _dataType; }
        }

        public Object LastValue
        {
            get { return _lastValue; }
        }

        private bool _isValueAsDBNull;

        public void SetValueAsDBNull()
        {
            _isDirty = true;
            _isValueAsDBNull = true;
        }

        public Object Value
        {
            get
            {
                if (_isValueAsDBNull)
                {
                    return DBNull.Value;
                }

                switch (_dataType)
                {
                    case DataType.String:
                        if (!String.IsNullOrEmpty(_stringValue))
                        {
                            return _stringValue;
                        }
                        break;

                    case DataType.Integer:
                        if (_intValue > 0)
                        {
                            return _intValue;
                        }
                        break;

                    case DataType.DateTime:
                        if (_dateTimeValue != DateTime.MinValue)
                        {
                            return _dateTimeValue;
                        }
                        break;

                    case DataType.Boolean:
                        return _booleanValue;

                    case DataType.Bytes:
                        return _bytesValue;
                }
                return null;
            }
            set
            {
                _isDirty = true;
                // The variable _isValueAsDBNull is automatically reset to false
                // when we enter a value.
                if (value != null && value != DBNull.Value)
                {
                    switch (_dataType)
                    {
                        case DataType.String:
                            _isValueAsDBNull = false;
                            _stringValue = Convert.ToString(value);
                            break;

                        case DataType.Integer:
                            _isValueAsDBNull = false;
                            _intValue = Convert.ToInt32(value);
                            break;

                        case DataType.DateTime:
                            _isValueAsDBNull = false;
                            try
                            {
                                _dateTimeValue = Convert.ToDateTime(value);
                            }
                            catch (FormatException)
                            {
                                throw new Exceptions.InvalidDataParameter(_name, "mm/dd/yyyy");
                            }
                            break;

                        case DataType.Boolean:
                            _isValueAsDBNull = false;
                            _booleanValue = Convert.ToBoolean(value);
                            break;

                        case DataType.Bytes:
                            _isValueAsDBNull = false;
                            _bytesValue = (byte[])value;
                            break;
                    }
                }
            }
        }

        /// <summary>
        /// Gets the maximum size of the string value.
        /// </summary>
        public int Length
        {
            get { return _length; }
        }

        /// <summary>
        /// Tracks whether the value properties have been set.
        /// </summary>
        public bool IsDirty
        {
            get { return _isDirty; }
        }

        /// <summary>
        /// Resets the internal value so that it can be used again.
        /// </summary>
        public void Reset()
        {
            _lastValue = Value;
            _stringValue = String.Empty;
            _intValue = -1;
            _isDirty = false;
            _booleanValue = false;
        }
    }
}
